#!/usr/bin/env python
"""
mailer

Class for sending mails
"""
import sys, os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEAudio import MIMEAudio
from email.MIMEImage import MIMEImage
from email.Header import Header
from email import Encoders
import mimetypes
import smtplib


def guess_encoding(s):

	if isinstance(s, unicode):
		try:
			s.encode("ascii")
			return "ascii"
		except UnicodeEncodeError:
			pass

		try:
			s.encode("iso-8859-15")
			return "iso-8859-15"
		except UnicodeEncodeError:
			pass

		return "utf-8"

	else:
		try:
			s.decode("ascii")
			return "ascii"
		except UnicodeDecodeError:
			pass

		raise UnicodeEncodeError, "cannot encode 'ascii' string, send a unicode string instead"


class Mailer ( object ):
	def __init__ ( self ):
		super ( Mailer, self ).__init__()
		self._port = 25
		self._server = "localhost"
		self._login = None
		self._passwd = None
		self._ssl = 0

	
	def set_server ( self, smtp_server, port = 25, login = '', passwd = '', ssl = 0 ):
		self._server = smtp_server
		self._port = port
		self._login = login
		self._passwd = passwd
		self._ssl = ssl


	def login ( self, username, password ):
		self._user = username
		self._passwd = password


	def send ( self, sender, dest, subject = "", body = "", attach = None,
			cc = None, bcc = None, reply_to = "", priority = "",
			extra_headers = None, html_body = None ):

		if not isinstance ( dest, list ): dest = [ dest ]

		if not attach: attach = []
		if not isinstance ( attach, list ): attach = [ attach ]

		body_enc = guess_encoding ( body )
		if isinstance ( body, unicode ): body = body.encode ( body_enc )

		body = MIMEText ( body, _charset = body_enc )
		if html_body:
			html_body_enc = guess_encoding ( html_body )
			if isinstance ( html_body, unicode ): html_body = html_body.encode ( html_body_enc )

			text_body = body
			html_body = MIMEText ( html_body, _subtype = "html", _charset = html_body_enc )

			body = MIMEMultipart ( _subtype = "alternative" )
			body.attach ( text_body )
			body.attach ( html_body )

		if attach:
			#ci sono degli attachment, il messaggio deve essere un multipart
			msg = MIMEMultipart()
			
			msg.attach ( body )

			for f in attach:
				ctype, encoding = mimetypes.guess_type ( f )
				if ctype is None or encoding is not None: ctype = 'application/octet-stream'
				maintype, subtype = ctype.split ( '/', 1 )
				if maintype == 'text':
					att = MIMEText ( file ( f, "rb" ).read(), _subtype = subtype )
				elif maintype == 'image':
					att = MIMEImage ( file ( f, "rb" ).read(), _subtype = subtype )
				elif maintype == 'audio':
					att = MIMEAudio ( file ( f, "rb" ).read(), _subtype = subtype )
				else:
					att = MIMEBase ( maintype, subtype )
					att.set_payload ( file ( f, "rb" ).read() )
					Encoders.encode_base64 ( att )
				att.add_header ( 'Content-Disposition', 'attachment', filename = os.path.split ( f )[1] )
				msg.attach ( att )

		else:
			#non ci sono attachment, il messaggio e' il semplice body
			msg = body
		
		#setto gli header standard
		msg [ "Subject" ] = subject
		msg [ "From" ] = sender
		msg [ "To" ] = ', '.join ( dest )

		#setto gli eventuali altri header
		if cc:
			if not isinstance ( cc, list ): cc = [ cc ]
			msg["Cc"] = ', '.join ( cc )
		else:
			cc = []

		if not bcc: bcc = []
		if not isinstance ( bcc, list ): bcc = [ bcc ]

		if reply_to: msg [ "Reply-To" ] = reply_to

		if priority: msg [ "X-Priority" ] = priority

		if not extra_headers: extra_headers = []
		for h in extra_headers:
			if len ( h ) == 2: msg [ h [ 0 ] ] = h [ 1 ]
			else: msg.add_header ( h [ 0 ], h [ 1 ], ** h [ 2 ] )

		rcpt_list = dest + cc + bcc

		for k, v in msg.items ():
			if not isinstance ( v, ( str, unicode ) ): v = str ( v )
			enc = guess_encoding ( v )
			if enc != "ascii": msg.replace_header ( k, Header ( v, enc ) )

		#SEND THE MAIL
		s = smtplib.SMTP ( self._server, self._port )
		if self._login:
			s.login ( self._login, self._passwd )

		s.sendmail ( sender, rcpt_list, msg.as_string () )
		s.close()


# TEST TEST TEST
if __name__ == '__main__':
	m = Mailer()
	m.set_server ( 'localhost' )
	m.send ( "john@os3.it", "john@buscone.it", u"Prova \u2625 \xe1 \xa4", "messaggio di prova" )

